package com.itheima.dubbo.api;

import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Publish;
import com.itheima.domain.mongo.Video;
import com.itheima.domain.vo.PageResult;
import org.apache.dubbo.config.annotation.Service;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.List;

/**
 * @author 阿鹏
 * @date 2021/1/29 17:07
 */
@Service
public class CommentApiImpl implements CommentApi {

    @Autowired
    private MongoTemplate mongoTemplate;


    @Override
    public long save(Comment comment) {
        // 补全数据保存到mongodb中
        comment.setId(ObjectId.get());
        comment.setCreated(System.currentTimeMillis());
        mongoTemplate.save(comment);

        // 修改publish表中的信息 修改动态的点赞/喜欢/评论的个数+1
        Query query = Query.query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getCollName(comment.getCommentType()), 1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);
        Publish publish = mongoTemplate.findAndModify(query, update, options, Publish.class);

        // 再次从comment表中查询最新的个数并返回
        return getTotal(publish, comment.getCommentType());
    }

    @Override
    public long saveOtherComment(Comment comment) {
        comment.setId(ObjectId.get());
        comment.setCreated(System.currentTimeMillis());
        mongoTemplate.save(comment);

        // 更新video表中的数据
        Query query = Query.query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getCollName(comment.getCommentType()), 1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);
        Video video = mongoTemplate.findAndModify(query, update, options, Video.class);

        return getTotal(video, comment.getCommentType());
    }

    @Override
    public PageResult<Comment> findComments(int page, int pagesize, String publishId) {
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(publishId))
                .and("commentType").is(2))
                .with(Sort.by(Sort.Order.desc("likeCount"), Sort.Order.desc("created")))
                .with(PageRequest.of(page-1, pagesize));
        // 查询2评论集合，通过点赞数倒序
        List<Comment> comments = mongoTemplate.find(query, Comment.class);
        long count = mongoTemplate.count(query, Comment.class);
        int pages = (int) Math.ceil(count * 1.0 / pagesize);
        return new PageResult<>((int) count, pagesize, pages, page, comments);
    }

    @Override
    public Comment findCommentByCommentId(String commentId) {
        Query query = Query.query(Criteria.where("id").is(new ObjectId(commentId)));
        return mongoTemplate.findOne(query, Comment.class);
    }

    @Override
    public PageResult<Comment> findCommentByUser(int page, int pagesize, int commentType, Long userId) {
        Query query = Query.query(
                Criteria.where("publishUserId").is(userId)
                        .and("commentType").is(commentType));
        List<Comment> commentList = mongoTemplate.find(query, Comment.class);
        long count = mongoTemplate.count(query, Comment.class);
        int pages = (int) Math.ceil(count * 1.0 / pagesize);

        return new PageResult<>((int)count, pagesize, pages, page, commentList);
    }

    @Override
    public long remove(Comment comment) {
        // 从comment表中删除当前记录
        Criteria criteria = Criteria.where("publishId").is(comment.getPublishId())
                .and("pubType").is(comment.getPubType())
                .and("userId").is(comment.getUserId());
        mongoTemplate.remove(new Query(criteria), Comment.class);

        // 更新publish动态表的数量
        Query query = Query.query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getCollName(comment.getCommentType()), -1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);
        Publish publish = mongoTemplate.findAndModify(query, update, options, Publish.class);

        // 返回最新的数据
        return getTotal(publish, comment.getCommentType());
    }

    @Override
    public long removeOtherComment(Comment comment) {
        Query query = new Query(Criteria.where("publishId").is(comment.getPublishId())
                .and("pubType").is(comment.getPubType())
                .and("userId").is(comment.getUserId()));
        mongoTemplate.remove(query, Comment.class);

        // 更新video表中的数据
        Query countQuery = Query.query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getCollName(comment.getCommentType()), -1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);
        Video video = mongoTemplate.findAndModify(countQuery, update, options, Video.class);

        return getTotal(video, comment.getCommentType());
    }

    public String getCollName(Integer commentType) {
        if (commentType == 1) {
            return "likeCount";
        } else if (commentType == 2) {
            return "commentCount";
        } else if (commentType == 3) {
            return "loveCount";
        }
        return "";
    }

    public long getTotal(Publish publish, Integer commentType) {
        if (commentType == 1){
            return publish.getLikeCount();
        } else if (commentType == 2){
            return publish.getCommentCount();
        }else if (commentType == 3){
            return publish.getLoveCount();
        }
        return 0;
    }

    public long getTotal(Video video, Integer commentType) {
        if (commentType == 1){
            return video.getLikeCount();
        } else if (commentType == 2){
            return video.getCommentCount();
        }else if (commentType == 3){
            return video.getLoveCount();
        }
        return 0;
    }
}
